package managers.dateManager.beginFrozen.beginChange;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.exceptions.TaskManagerException;
import org.tbjd.client.managers.TaskManager;
import org.tbjd.client.states.StateBeginFrozenSPEC;

import factories.TaskFactory;

/**
 * <p>
 * Test TaskManager's methods
 * </p>
 * <p>
 * <b>Case</b>
 * </p>
 * <p>
 * A task with multiple predecessors and successors as well as isolated tasks
 * </p>
 * <p>
 * <b>Action</b>
 * </p>
 * <p>
 * BeginDate of the task "task" is changed
 * </p>
 * <b> Expected</b>
 * <ul>
 * <li>update EndDate of "task"</li>
 * </ul>
 * </p>
 * 
 * @author Michael Martin
 * @author Antonio Carrozzini
 * @version 1.0
 * 
 */
public class BeginFrozen_BeginChange_UpdatePredecessorsAndSuccessors_Basic extends TestCase {

	private Map<Integer, Object> map = null;
	private Logger log = Logger.getLogger("console");
	private DateFormat df = DateFormat.getInstance();
	private Task task = null;
	private TaskManager dateManager = new TaskManager();

	protected void setUp() throws Exception {
		df = new SimpleDateFormat("dd.MM.yyyy");

		// create a list of tasks with pred. / succ.
		// here, task has 2 predecessors (p1 & p2) and 2 successors (s1 & s2)
		// o p1 manual
		// o t1 manual
		// o p2 manual
		// o task manual
		// o t2 manual
		// o s1 manual
		// o s2 manual
		// o t3 manual

		Task p1 = TaskFactory.getInstance();
		p1.setName("p1");
		p1.setBeginDate(df.parse("1.1.2009"));
		p1.setEndDate(df.parse("2.1.2009"));
		p1.setDuration(24);
		p1.setState(new StateBeginFrozenSPEC(p1.getState().getDurationModeState()));

		Task t1 = TaskFactory.getInstance();
		t1.setName("t1");
		t1.setBeginDate(df.parse("1.5.2009"));
		t1.setEndDate(df.parse("3.5.2009"));
		t1.setDuration(48);
		t1.setState(new StateBeginFrozenSPEC(t1.getState().getDurationModeState()));

		Task p2 = TaskFactory.getInstance();
		p2.setName("p2");
		p2.setBeginDate(df.parse("2.1.2009"));
		p2.setEndDate(df.parse("3.1.2009"));
		p2.setDuration(24);
		p2.setState(new StateBeginFrozenSPEC(p2.getState().getDurationModeState()));

		this.task = TaskFactory.getInstance();
		this.task.setName("task");
		this.task.setBeginDate(df.parse("4.1.2009"));
		this.task.setEndDate(df.parse("10.1.2009"));
		this.task.setDuration(144);
		this.task.setState(new StateBeginFrozenSPEC(task.getState().getDurationModeState()));

		Task t2 = TaskFactory.getInstance();
		t2.setName("t2");
		t2.setBeginDate(df.parse("1.1.2009"));
		t2.setEndDate(df.parse("3.1.2009"));
		t2.setDuration(48);
		t2.setState(new StateBeginFrozenSPEC(t2.getState().getDurationModeState()));

		Task s1 = TaskFactory.getInstance();
		s1.setName("s1");
		s1.setBeginDate(df.parse("11.1.2009"));
		s1.setEndDate(df.parse("14.1.2009"));
		s1.setDuration(72);
		s1.setState(new StateBeginFrozenSPEC(s1.getState().getDurationModeState()));

		Task s2 = TaskFactory.getInstance();
		s2.setName("s2");
		s2.setBeginDate(df.parse("15.1.2009"));
		s2.setEndDate(df.parse("23.1.2009"));
		s2.setDuration(192);
		s2.setState(new StateBeginFrozenSPEC(s2.getState().getDurationModeState()));

		Task t3 = TaskFactory.getInstance();
		t3.setName("t3");
		t3.setBeginDate(df.parse("5.6.2009"));
		t3.setEndDate(df.parse("12.6.2009"));
		t3.setDuration(168);
		s2.setState(new StateBeginFrozenSPEC(t3.getState().getDurationModeState()));

		p1.addSuccessor(this.task);
		p2.addSuccessor(this.task);
		this.task.addSuccessor(s1);
		this.task.addSuccessor(s2);

		super.setUp();
	}

	public void testReturnedBeanListNotNull() {
		log.debug(" === testReturnedBeanListNotNull");
		log.debug("original BeginDate = " + this.task.getBeginDate());
		log.debug("original EndDate = " + this.task.getEndDate());

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call TaskManager...");
		try {
			assertNotNull("Updated bean list isn't null", dateManager.manageDates(map));

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		System.out.println("");
	}

	public void testReturnedBeanListNotEmpty() {
		log.debug(" === testReturnedBeanListNotEmpty");
		log.debug("original BeginDate = " + this.task.getBeginDate());
		log.debug("original EndDate = " + this.task.getEndDate());

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}
		assertTrue("Updated bean list size > 0", updatedBeans.size() > 0);

		System.out.println("");
	}

	public void testReturnedListSize() {
		log.debug(" === testReturnedListSize");
		log.debug("original BeginDate = " + this.task.getBeginDate());
		log.debug("original EndDate = " + this.task.getEndDate());

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}
		assertEquals("Updated bean list size = 1", 1,updatedBeans.size());

		System.out.println("");
	}

	public void testReturnedBeanIsSameAsOriginal() {
		log.debug(" === testReturnedBeanIsSameAsOriginal");
		log.debug("original BeginDate = " + task.getBeginDate());
		log.debug("original EndDate = " + task.getEndDate());

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals("Task given and received are equals", this.task, updatedBeans.get(0));

		System.out.println("");
	}

	public void testBeginDateHasBeenChanged() {
		log.debug(" === testBeginDateHasBeenChanged");

		Date originalBeginDate = this.task.getBeginDate();
		Date originalEndDate = this.task.getEndDate();
		float originalDuration = this.task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			e.printStackTrace();
			fail();
		}

		assertEquals("Assert beginDate has been udated with new BeginDate", newBeginDate, updatedBeans.get(0).getBeginDate());

		System.out.println("");
	}

	public void testEndDateHasChanged() {
		log.debug(" === testEndDateHasChanged");

		Date originalBeginDate = this.task.getBeginDate();
		Date originalEndDate = this.task.getEndDate();
		float originalDuration = this.task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		Date expectedEndDate = null;
		try {
			expectedEndDate = df.parse("7.1.2009");

		} catch (ParseException e) {
			fail(e.getMessage());

		}
		assertEquals("Assert EndDate has correct value", expectedEndDate, updatedBeans.get(0).getEndDate());

		System.out.println("");
	}

	public void testDurationHasNotBeenChanged() {
		log.debug(" === testDurationHasNotBeenChanged");

		Date originalBeginDate = this.task.getBeginDate();
		Date originalEndDate = this.task.getEndDate();
		float originalDuration = this.task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");
		} catch (ParseException e1) {
			fail(e1.getMessage());
		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("compute with new BeginDate = " + newBeginDate + "...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			e.printStackTrace();
			fail();
		}

		assertEquals("Assert duration value is the same", originalDuration, updatedBeans.get(0).getDuration());

		System.out.println("");
	}

	public void testRevertGivesOriginalBeginDate() {
		log.debug(" === testRevertGivesOriginalBeginDate");

		Date originalBeginDate = this.task.getBeginDate();
		Date originalEndDate = this.task.getEndDate();
		float originalDuration = this.task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		log.debug("call dateManager with new BeginDate...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original BeginDate...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, originalBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved BeginDate = " + updatedBeans.get(0).getBeginDate() + " & original BeginDate = " + originalBeginDate);
		assertEquals("Assert BeginDate reverted to original", originalBeginDate, updatedBeans.get(0).getBeginDate());

		System.out.println("");
	}

	public void testRevertGivesOriginalEndDate() {
		log.debug(" === testRevertGivesOriginalEndDate");

		Date originalBeginDate = this.task.getBeginDate();
		Date originalEndDate = this.task.getEndDate();
		float originalDuration = this.task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		log.debug("call dateManager with new BeginDate = " + newBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original BeginDate = " + originalBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, originalBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());
		}

		log.debug("retrieved EndDate = " + updatedBeans.get(0).getEndDate() + " & original BeginDate = " + originalEndDate);
		assertEquals("Assert BeginDate reverted to original", originalEndDate, updatedBeans.get(0).getEndDate());

		System.out.println("");
	}

	public void testRevertGivesOriginalDuration() {
		log.debug(" === testRevertGivesOriginalDuration");

		Date originalBeginDate = this.task.getBeginDate();
		Date originalEndDate = this.task.getEndDate();
		float originalDuration = this.task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("31.5.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		log.debug("call dateManager with new BeginDate = " + newBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original BeginDate = " + originalBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_beginDate, originalBeginDate);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());
		}

		assertEquals("Assert Duration reverted to original", originalDuration, updatedBeans.get(0).getDuration());

		System.out.println("");
	}

}